
#ifndef INC_TIMER_H_
#define INC_TIMER_H_

extern volatile uint32_t timer_overflow_count; // 溢出次数计数器

// 获取单片机上电以来的时间，单位us
static inline uint64_t get_absolute_time(void) {
    uint32_t overflow_count;
    uint32_t timer_count;

    do {
        // 先读取溢出次数，再读取定时器值
        overflow_count = timer_overflow_count;
        timer_count = LL_TIM_GetCounter(TIM2);

        // 若读取后溢出次数未变化，说明数据一致
    } while (overflow_count != timer_overflow_count);

    // 合并为64位时间：(溢出次数 << 32) + 当前计数值
    return ((uint64_t)overflow_count << 32) + timer_count;
}

// us延时（忙等待）
static inline void sleep_us(uint64_t us) {
    uint64_t start = get_absolute_time();
    while (get_absolute_time() - start < us);
}

// ms延时（忙等待）
// 功能与库函数LL_mDelay类似，但是不要去使用LL_mDelay
// LL_mDelay依赖的systick定时器，我用来产生10KHz中断了
static inline void sleep_ms(uint64_t ms) {
    sleep_us(ms * 1000);
}

// 延时到指定绝对时间(us)
static inline void sleep_until(uint64_t target_time) {
    while (get_absolute_time() < target_time);
}


// 精确延时函数，延时指定的指令周期数，如果中间出现中断，延时会变长
// 实际延时周期 = 3 × cycles周期
static inline void sleep_cycles(uint32_t cycles)
{
    __asm volatile (
        "1: subs %0, %0, #1 \n"  // 减1并设置标志位 (1周期)
        "   bne 1b         \n"  // 如果不为0则跳转 (1或2周期，跳转时2周期)
        : "+r" (cycles)         // 输入输出操作数
        :                       // 无输入操作数
        : "cc"                  // 破坏的条件码寄存器
    );
}

#endif /* INC_TIMER_H_ */
